1. Decorators

  • Definition: Decorators are a way to modify or extend the behavior of functions or methods without changing their actual code.
  • Usage: They're often used for logging, enforcing access control, instrumentation, and more.
  • Example:

    python
    def decorator(func):
    def wrapper():
    print("Before function call")
    func()
    print("After function call")
    return wrapper
    @decorator
    def say_hello():
    print("Hello")
    say_hello()

    2. Context Managers

  • Definition: Context managers allow you to allocate and release resources precisely when you want to.
  • Usage: They're typically used with the with statement for resource management (e.g., file handling, database connections).
  • Example:

    python
    class MyContextManager:
    def __enter__(self):
    print("Entering the context")
    return self
    def __exit__(self, exc_type, exc_value, traceback):
    print("Exiting the context")
    with MyContextManager():
    print("Inside the context")

    3. Metaclasses

  • Definition: A metaclass defines the behavior of a class. It's the "class of a class."
  • Usage: Used for dynamically creating classes, adding attributes, and more complex custom behaviors at the class level.
  • Example:

    python
    class Meta(type):
    def __new__(cls, name, bases, dct):
    dct['custom_attr'] = 'Hello from Meta'
    return super().__new__(cls, name, bases, dct)
    class MyClass(metaclass=Meta):
    pass
    obj = MyClass()
    print(obj.custom_attr)

    4. Generators and Iterators

  • Definition: Generators are special types of iterators that allow you to iterate over data lazily (i.e., one item at a time) without loading all the data into memory.
  • Usage: Useful when working with large datasets or streams.
  • Example:

    python
    def count_up_to(max):
    count = 1
    while count <= max:
    yield count
    count += 1
    counter = count_up_to(5)
    for num in counter:
    print(num)

    5. Concurrency (Threading, Multiprocessing)

  • Definition: Python offers multiple approaches for concurrent programming, including threads and processes.
  • Usage: Threads are best for I/O-bound tasks, while processes are better for CPU-bound tasks.
  • Example (Threading):

    python
    import threading
    def print_numbers():
    for i in range(5):
    print(i)
    thread = threading.Thread
    (target=print_numbers)
    thread.start()
    thread.join()
    # Wait for thread to finish

    Example: (Multiprocessing):

    python
    mport multiprocessing
    def print_numbers():
    for i in range(5):
    print(i)
    process = multiprocessing.
    Process(target=
    print_numbers) process.start()
    process.join() # Wait for
    process to finish

    6. Asyncio

  • Definition: Asyncio is a library for writing concurrent code using the async and await keywords. It's used for asynchronous I/O-bound tasks like web scraping, network applications, etc.
  • Usage: Enables single-threaded, asynchronous programming with event loops.
  • Example:

    python
    import asyncio
    async def fetch_data():
    print("Fetching data...")
    await asyncio.sleep(2)
    print("Data fetched!")
    async def main():
    await fetch_data()
    asyncio.run(main())

    7. Type Hints and Annotations

  • Definition: Python supports optional type annotations to help with static analysis, readability, and code reliability.
  • Usage: They can be used to specify function argument types, return types, and variables.
  • Example:

    python
    def greet(name: str) -> str:
    return f"Hello, {name}"
    greeting = greet("Alice")
    print(greeting)

    8. Functional Programming in Python

  • Definition: Python supports some aspects of functional programming, such as first-class functions, map(), filter(), and reduce().
  • Usage: You can use these functions to avoid explicit loops and keep your code concise.
  • Example:

    python
    from functools import reduce
    numbers = [1, 2, 3, 4, 5]
    total = reduce(lambda x, y: x + y, numbers)
    print(total)

    9. Advanced Data Structures (e.g., collections module)

  • Definition: Python’s collections module provides specialized data structures like deque, Counter, defaultdict, and OrderedDict.
  • Usage: These structures can be more efficient or expressive than built-in types for certain tasks.
  • Example:

    python
    from collections import Counter
    words = ["apple", "banana", "apple", "cherry"]
    count = Counter(words)
    print(count)

    10. Design Patterns

  • Definition: Design patterns are common solutions to recurring software design problems. Python supports patterns like Singleton, Factory, Observer, and more.
  • Usage: These patterns help write maintainable and reusable code.
  • Example (Singleton):

    python
    class Singleton:
    _instance = None
    def __new__(cls):
    if cls._instance is None:
    cls._instance = super().__new__(cls)
    return cls._instance
    obj1 = Singleton()
    obj2 = Singleton()
    print(obj1 is obj2) # True

    11. Cython for Performance Optimization

  • Definition: Cython is a superset of Python that allows you to compile Python code to C for improved performance.
  • Usage: Useful for performance-critical code, such as numerical computations.
  • 12. Python Memory Management & Garbage Collection

  • Definition: Python uses automatic memory management and garbage collection to reclaim memory used by objects that are no longer in use.
  • Usage: Knowing how Python handles memory can help you optimize the performance and reduce memory leaks.